
using System;
using System.Collections;
using System.Collections.Generic;
using MyFrame.Load;
using MyFrame.Single;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Pool;
using Plugin.Tool;
using Cysharp.Threading.Tasks;

namespace MyFrame.Pool
{

    public class PoolMgr : SingletonMonoGlobal<PoolMgr>
    {
        /// <summary>
        /// 一个类型对应一个对象池  顺序是预制体顺序
        /// </summary>
        private Dictionary<string, ObjectPool<GameObject>> poolDic = new();
        private Dictionary<string, PoolData> prePoolDic = new();
        //引用类型
        private Dictionary<Type, object> objPoolDic = new();

        /// <summary>
        /// 保存预设体 方便复用
        /// </summary>
        private Dictionary<string, GameObject> prefabs = new();


        /// <summary>
        ///  用于预创建对象,将自动扩容，事实上音乐播放不需要特殊处理,  所以废弃
        /// </summary>
        /// <param name="objName"></param>
        /// <param name="size"></param>
        // public void CreatePool(string objName, int size = 10)
        // {
        //     GameObject prefab = GetPrefab(objName);

        //     PoolData pool;
        //     if (prePoolDic.ContainsKey(objName))
        //     {
        //         pool = prePoolDic[objName];
        //     }
        //     else
        //     {
        //         pool = new PoolData(prefab, gameObject);
        //         prePoolDic.Add(objName, pool);
        //     }

        //     for (int i = 0; i < size; i++)
        //     {
        //         GameObject newObj = Instantiate(prefab);
        //         newObj.name = objName;
        //         pool.Push(newObj);
        //     }

        //     return;
        // }


        /// <summary>
        ///  获取对象
        /// </summary>
        public GameObject GetObj(string objName, Vector3 position = default, Quaternion rotation = default, Action<GameObject> preCallback = null)
        {
            // 对象池不存在则创建
            if (poolDic.ContainsKey(objName))
            {
                //池子有东西，可拿  
                GameObject result = poolDic[objName].Get();

                result.transform.SetPositionAndRotation(position, rotation);
                return result;
            }
            else
            {
                //池子没有东西，创建
                GameObject prefab = GetPrefab(objName);

                if (position != default) prefab.transform.position = position;
                if (rotation != default) prefab.transform.rotation = rotation;

                var newPool = CreatePool(prefab, objName);
                poolDic.Add(objName, newPool);
                return newPool.Get();
            }
        }
        private ObjectPool<GameObject> CreatePool(GameObject prefab, string objName)
        {
            Transform parent = new GameObject(prefab.name).transform;
            parent.SetParent(transform);
            var newPool = new ObjectPool<GameObject>(
                () =>
                {
                    var newObj = Instantiate(prefab, parent);
                    newObj.name = objName;
                    return newObj;
                },
                e =>
                {
                    e.SetActive(true);
                },
                e => e.SetActive(false),
                e => Destroy(e)
            // defaultCapacity: 10
            );
            return newPool;
        }

        private GameObject GetPrefab(string objName)
        {
            GameObject prefab = null;
            //如果已经加载过该预设体
            if (prefabs.ContainsKey(objName))
            {
                prefab = prefabs[objName];
            }
            else     //如果没有加载过该预设体
            {
                //加载预设体
                // prefab = Resources.Load<GameObject>(objName);
                try
                {
                    prefab = AAMgr.LoadAsset<GameObject>(objName);
                    prefab.name = objName;
                    //更新字典
                    prefabs.Add(objName, prefab);
                }
                catch
                {
                    Debug.LogError("加载预设体失败：" + objName);
                }
            }
            return prefab;
        }

        #region  引用类型对象池
        /// <summary>
        /// 回收直接用clear
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        // public T GetObj<T>() where T : class
        // {
        //     if (objPoolDic.ContainsKey(typeof(T)))
        //     {
        //         Debug.Log("对象数量" + ((ObjectPool<T>)objPoolDic[typeof(T)]).CountAll);

        //         return ((ObjectPool<T>)objPoolDic[typeof(T)]).Get();
        //     }
        //     else
        //     {
        //         var newPool = CreateObjPool<T>();
        //         objPoolDic.Add(typeof(T), newPool);
        //         return newPool.Get() as T;
        //     }
        // }
        #endregion


        #region 销毁与获取
        public void Clear()
        {
            foreach (var pool in poolDic)
            {
                pool.Value.Clear();
            }

            foreach (var pool in prePoolDic)
            {
                pool.Value.Clear();
            }

            // foreach (var pool in objPoolDic)
            // {
            //     var clearMethod = pool.GetType().GetMethod("Clear");
            //     clearMethod?.Invoke(pool, null);
            // }
            poolDic.Clear();
            prePoolDic.Clear();
            // objPoolDic.Clear();
        }

        public void Release(GameObject obj)
        {
            if (poolDic.ContainsKey(obj.name))
            {
                if (obj.activeSelf == false)
                {
                    string objName = obj.name;
                    Debug.LogWarning($"对象'{objName}' 已经回收.");
                    return;
                }
                poolDic[obj.name].Release(obj);
            }
            else if (prePoolDic.ContainsKey(obj.name))
            {
                prePoolDic[obj.name].Release(obj);
            }
            else
            {
                Destroy(obj);
            }
        }
        // private IEnumerator ReleaseAsync(ObjectPool<GameObject> objPool, GameObject obj)
        // {
        //     yield return new WaitForSeconds(1.5f);
        //     objPool.Release(obj);
        // }

        private ObjectPool<T> CreateObjPool<T>() where T : class
        {
            var newPool = new ObjectPool<T>(
                () => Activator.CreateInstance<T>(),
                null,
                null
            );
            return newPool;
        }


        #endregion
    }


    #region  小对象池
    public class PoolData
    {
        /// <summary>
        /// 预制体的父节点，不是顶层
        /// </summary>
        public GameObject fatherObj;
        // 容器
        public Queue<GameObject> poolQueue;

        public int Count => poolQueue.Count;

        public PoolData(GameObject prefab, GameObject ancestor)
        {
            fatherObj = new GameObject(prefab.name);
            fatherObj.transform.SetParent(ancestor.transform);
            poolQueue = new Queue<GameObject>();
        }

        // 添加
        public void Push(GameObject obj)
        {
            obj.SetActive(false);
            poolQueue.Enqueue(obj);
            obj.transform.parent = fatherObj.transform;
        }

        //   释放
        public void Release(GameObject obj)
        {
            obj.SetActive(false);
            poolQueue.Enqueue(obj);
        }

        public GameObject Get()
        {
            GameObject obj = poolQueue.Dequeue();
            obj.SetActive(true);
            return obj;
        }

        public void Clear()
        {
            poolQueue.Clear();
        }
    }
    #endregion
    // public class PoolMgr : SingletonMono<PoolMgr>
    // {

    // public Dictionary<String, PoolData> poolDic = new();

    // private GameObject poolObj;

    // public void GetObject(string name, UnityAction<GameObject> callback = null)
    // {
    //     if (poolDic.ContainsKey(name) && poolDic[name].poolList.Count > 0)
    //     {
    //         //池子有东西，可拿
    //         callback(poolDic[name].GetObj());
    //     }
    //     else
    //     {
    //         //池子没有东西，创建
    //         ResMgr.Instance.LoadAsync<GameObject>(name, (obj) =>
    //         {
    //             obj.name = name;
    //             callback(obj);
    //         });
    //     }
    // }

    //存入
    // public void PushObject(string name, GameObject obj)
    // {
    //     if (poolObj == null)
    //         poolObj = new GameObject("PoolObj");

    //     if (poolDic.ContainsKey(name))
    //     {
    //         poolDic[name].PushObj(obj);
    //     }
    //     else
    //     {
    //         poolDic.Add(name, new PoolData(obj, poolObj));
    //     }
    // }

    /// <summary>
    /// 场景切换，清空缓存池
    /// </summary>
    // public void Clear()
    // {
    //     poolDic.Clear();
    //     poolObj = null;
    // }
}
